// src/utils/interpreter.ts
import * as acorn from "acorn";

/** ---------- 作用域变量与作用域管理 ---------- */
class ScopeVar {
	kind: "var" | "let" | "const";
	value: any;
	constructor(kind: "var" | "let" | "const", value: any) {
		this.kind = kind;
		this.value = value;
	}
	$set(v: any) {
		if (this.kind === "const") throw new Error("Assignment to constant variable");
		this.value = v;
	}
	$get() {
		return this.value;
	}
}

class Scope {
	parent: Scope | null;
	table: Record<string, ScopeVar> = {};
	isAsyncContext: boolean = false; // 是否允许异步操作（如await）
	isTopLevel: boolean = false; // 是否为顶层作用域（模块级）
	
	constructor(parent: Scope | null = null, isAsyncContext: boolean = false, isTopLevel: boolean = false) {
		this.parent = parent;
		this.isAsyncContext = isAsyncContext;
		this.isTopLevel = isTopLevel;
	}
	find(name: string): ScopeVar | null {
		if (Object.prototype.hasOwnProperty.call(this.table, name)) {
			return this.table[name];
		}
		return this.parent ? this.parent.find(name) : null;
	}
	declare(kind: "var" | "let" | "const", name: string, value: any) {
		if (!this.table[name]) {
			this.table[name] = new ScopeVar(kind, value);
		}
	}
	createChild(isAsync?: boolean, isTopLevel?: boolean): Scope {
		return new Scope(
			this,
			isAsync ?? this.isAsyncContext,
			isTopLevel ?? this.isTopLevel
		);
	}
}

/** ---------- 包装 setTimeout ---------- */
const hostSetTimeout = (globalThis as any).setTimeout;
function wrappedSetTimeout(cb: any, delay?: number, ...args: any[]) {
	if (typeof cb === "function") {
		return hostSetTimeout(cb, delay, ...args);
	}
	if (cb && cb.__node && cb.__scope) {
		return hostSetTimeout(() => {
			try {
				evaluate(cb.__node.body, new Scope(cb.__scope));
			} catch (err) {
				console.error("定时器回调出错:", err);
			}
		}, delay);
	}
	console.warn("setTimeout: 第一个参数不可调用", cb);
	return hostSetTimeout(() => { }, delay);
}

/** ---------- 默认API注入 ---------- */
const defaultApi: Record<string, any> = {
	console,
	JSON,
	Math,
	Date,
	Number,
	String,
	Boolean,
	Array,
	Object,
	clearTimeout,
	setInterval,
	clearInterval,
	setTimeout: wrappedSetTimeout,
	Promise: Promise,
};

/** ---------- 核心执行函数（支持同步/异步切换） ---------- */
// 同步执行函数（无返回Promise）
function evaluateSync(node: any, scope: Scope): any {
	switch (node.type) {
		case "Program": {
			let result;
			for (const stmt of node.body) {
				// 顶层同步执行时，遇到需要异步的节点则抛出特殊标记
				result = evaluateSync(stmt, scope);
			}
			return result;
		}

		case "ExpressionStatement":
			return evaluateSync(node.expression, scope);

		case "Literal":
			return node.value;

		case "Identifier": {
			const v = scope.find(node.name);
			if (!v) throw new Error(`变量未定义: ${node.name}`);
			return v.$get();
		}

		case "VariableDeclaration":
			for (const decl of node.declarations) {
				const initVal = decl.init ? evaluateSync(decl.init, scope) : undefined;
				scope.declare(node.kind, decl.id.name, initVal);
			}
			return;

		case "CallExpression": {
			if (node.callee.type === "MemberExpression") {
				const obj = evaluateSync(node.callee.object, scope);
				const prop = node.callee.computed
					? evaluateSync(node.callee.property, scope)
					: node.callee.property.name;
				const fn = obj[prop];
				const args = node.arguments.map((a: any) => evaluateSync(a, scope));
				if (typeof fn !== "function") throw new Error(`${prop} 不是函数`);
				
				// 同步调用：直接执行，不处理Promise（若返回Promise则保留，但同步上下文不await）
				return fn.call(obj, ...args);
			} else {
				const callee = evaluateSync(node.callee, scope);
				const args = node.arguments.map((a: any) => evaluateSync(a, scope));
				if (typeof callee === "function") {
					return callee(...args);
				}
				throw new Error("尝试调用的对象不是函数");
			}
		}

		case "MemberExpression": {
			const obj = evaluateSync(node.object, scope);
			const prop = node.computed ? evaluateSync(node.property, scope) : node.property.name;
			return obj[prop];
		}

		case "AssignmentExpression": {
			if (node.left.type === "Identifier") {
				const v = scope.find(node.left.name);
				if (!v) throw new Error(`变量未定义: ${node.left.name}`);
				const val = evaluateSync(node.right, scope);
				v.$set(val);
				return val;
			}
			if (node.left.type === "MemberExpression") {
				const obj = evaluateSync(node.left.object, scope);
				const prop = node.left.computed
					? evaluateSync(node.left.property, scope)
					: node.left.property.name;
				const val = evaluateSync(node.right, scope);
				obj[prop] = val;
				return val;
			}
			throw new Error("不支持的赋值类型");
		}

		case "ArrowFunctionExpression":
		case "FunctionExpression": {
			const isAsync = node.async;
			const originalScope = scope; // 保存原始作用域（关键：用于纯净调用）
			const originalNode = node;   // 保存原始AST节点
			  
			const func = isAsync 
				? async (...args: any[]) => { // 异步函数仍返回Promise
					// 用原始作用域创建子作用域（而非当前scope，避免包装层级问题）
					const funcScope = originalScope.createChild(true);
					// 绑定外部传入的参数到函数参数
					originalNode.params.forEach((p: any, i: number) => {
						funcScope.declare("let", p.name, args[i]);
					});
					return await evaluate(originalNode.body, funcScope);
				}
				: (...args: any[]) => { // 同步函数同步执行
					const funcScope = scope.createChild(false);
					node.params.forEach((p: any, i: number) => {
						funcScope.declare("let", p.name, args[i]);
					});
					return evaluateSync(node.body, funcScope); // 用同步执行
				};
			(func as any).__node = node;
			(func as any).__scope = scope;
			(func as any).__isAsync = isAsync;
			return func;
		}

		case "BlockStatement": {
			let val;
			for (const stmt of node.body) {
				val = evaluateSync(stmt, scope);
			}
			return val;
		}

		case "ReturnStatement": {
			return node.argument ? evaluateSync(node.argument, scope) : undefined;
		}

		// 同步上下文遇到await直接报错（除非是顶层）
		case "AwaitExpression": {
			if (scope.isTopLevel) {
				// 顶层await需要切换到异步处理，抛出特殊标记
				throw { type: "TOP_LEVEL_AWAIT", node: node.argument };
			}
			throw new Error("同步函数中不允许使用await");
		}

		// 其他同步节点（逻辑运算、二元运算等）保持同步处理
		case "LogicalExpression": {
			const left = evaluateSync(node.left, scope);
			if (node.operator === "&&") {
				return left && evaluateSync(node.right, scope);
			}
			if (node.operator === "||") {
				return left || evaluateSync(node.right, scope);
			}
			throw new Error(`不支持的逻辑运算符: ${node.operator}`);
		}

		case "UnaryExpression": {
			const arg = evaluateSync(node.argument, scope);
			switch (node.operator) {
				case "!": return !arg;
				case "typeof": return typeof arg;
				case "+": return +arg;
				case "-": return -arg;
				default: throw new Error(`不支持的一元运算符: ${node.operator}`);
			}
		}

		case "BinaryExpression": {
			const left = evaluateSync(node.left, scope);
			const right = evaluateSync(node.right, scope);
			switch (node.operator) {
				case "==": return left == right;
				case "!=": return left != right;
				case "===": return left === right;
				case "!==": return left !== right;
				case "<": return left < right;
				case "<=": return left <= right;
				case ">": return left > right;
				case ">=": return left >= right;
				case "+": return left + right;
				case "-": return left - right;
				case "*": return left * right;
				case "/": return left / right;
				case "%": return left % right;
				default: throw new Error(`不支持的二元运算符: ${node.operator}`);
			}
		}

		case "IfStatement": {
			const test = evaluateSync(node.test, scope);
			if (test) {
				return evaluateSync(node.consequent, scope);
			} else if (node.alternate) {
				return evaluateSync(node.alternate, scope);
			}
			return;
		}

		case "ObjectExpression": {
			const obj: any = {};
			for (const prop of node.properties) {
				if (prop.type === "Property") {
					const key = prop.key.type === "Identifier" ? prop.key.name : evaluateSync(prop.key, scope);
					const value = evaluateSync(prop.value, scope);
					obj[key] = value;
				} else if (prop.type === "SpreadElement") {
					const spreadValue = evaluateSync(prop.argument, scope);
					Object.assign(obj, spreadValue);
				}
			}
			return obj;
		}

		case "ArrayExpression": {
			const elements = [];
			for (const elem of node.elements) {
				if (elem?.type === "SpreadElement") {
					const spreadValue = evaluateSync(elem.argument, scope);
					if (Array.isArray(spreadValue)) {
						elements.push(...spreadValue);
					} else {
						throw new Error(`Cannot spread non-iterable value: ${spreadValue}`);
					}
				} else if (elem) {
					elements.push(evaluateSync(elem, scope));
				} else {
					elements.push(undefined);
				}
			}
			return elements;
		}
		
		case "NewExpression": {
		    // 先获取构造函数
		    const constructor = evaluateSync(node.callee, scope);
		    if (typeof constructor !== "function") {
		        throw new Error("new 操作符后的对象不是构造函数");
		    }
		    
		    // 处理参数（可能有多个）
		    const args = node.arguments.map((arg: any) => evaluateSync(arg, scope));
		    
		    // 使用 new 关键字调用构造函数
		    // 通过 Reflect.construct 模拟 new 操作，支持参数列表
		    return Reflect.construct(constructor, args);
		}
		
		case "ChainExpression": {
		    // 处理可选链表达式（如 a?.b?.c）
		    const expr = node.expression;
		    // 从最内层开始计算
		    let value = evaluateSync(expr, scope);
		    // 检查是否为 null 或 undefined
		    if (value === null || value === undefined) {
		        return undefined;
		    }
		    return value;
		}
		
		// 同时需要处理 OptionalMemberExpression（可选链的成员访问）
		case "OptionalMemberExpression": {
		    const obj = evaluateSync(node.object, scope);
		    // 如果对象为 null 或 undefined，直接返回 undefined
		    if (obj === null || obj === undefined) {
		        return undefined;
		    }
		    // 否则按照普通 MemberExpression 处理属性访问
		    const prop = node.computed 
		        ? evaluateSync(node.property, scope) 
		        : node.property.name;
		    return obj[prop];
		}
		
		// 处理 OptionalCallExpression（可选链的函数调用）
		case "OptionalCallExpression": {
		    const callee = evaluateSync(node.callee, scope);
		    // 如果调用对象为 null 或 undefined，直接返回 undefined
		    if (callee === null || callee === undefined) {
		        return undefined;
		    }
		    // 处理参数
		    const args = node.arguments.map((a: any) => evaluateSync(a, scope));
		    // 处理可选链调用的上下文对象（如 obj?.method?.() 中的 obj）
		    const context = node.callee.type === "MemberExpression" 
		        ? evaluateSync((node.callee as any).object, scope)
		        : undefined;
		    if (typeof callee !== "function") {
		        throw new Error("可选链调用的目标不是函数");
		    }
		    return context ? callee.call(context, ...args) : callee(...args);
		}


		default:
			console.warn("未实现的同步AST节点类型:", node.type);
			return undefined;
	}
}

// 异步执行函数（处理顶层await及异步上下文）
async function evaluateAsync(node: any, scope: Scope): Promise<any> {
	switch (node.type) {
		case "Program": {
			let result;
			for (const stmt of node.body) {
				result = await evaluateAsync(stmt, scope);
			}
			return result;
		}

		case "ExpressionStatement":
			return await evaluateAsync(node.expression, scope);

		case "AwaitExpression": {
			const value = await evaluateAsync(node.argument, scope);
			return await Promise.resolve(value); // 等待Promise完成
		}

		// 其他需要异步处理的节点（复用原异步逻辑的核心部分）
		case "CallExpression": {
			if (node.callee.type === "MemberExpression") {
				const obj = await evaluateAsync(node.callee.object, scope);
				const prop = node.callee.computed
					? await evaluateAsync(node.callee.property, scope)
					: node.callee.property.name;
				const fn = obj[prop];
				const args = await Promise.all(node.arguments.map((a: any) => evaluateAsync(a, scope)));
				if (typeof fn !== "function") throw new Error(`${prop} 不是函数`);
				const result = fn.call(obj, ...args);
				return result instanceof Promise ? await result : result;
			} else {
				const callee = await evaluateAsync(node.callee, scope);
				const args = await Promise.all(node.arguments.map((a: any) => evaluateAsync(a, scope)));
				if (typeof callee === "function") {
					const result = callee(...args);
					return (callee as any).__isAsync ? await result : result;
				}
				throw new Error("尝试调用的对象不是函数");
			}
		}

		// 其他节点默认用同步执行（已确保无异步操作）
		default:
			return evaluateSync(node, scope);
	}
}

// 入口执行函数（协调同步/异步）
function evaluate(node: any, scope: Scope): any {
	try {
		// 优先同步执行
		return evaluateSync(node, scope);
	} catch (err: any) {
		// 若顶层遇到await，切换到异步执行
		if (err.type === "TOP_LEVEL_AWAIT" && scope.isTopLevel) {
			return (async () => {
				// 先处理await的表达式
				const awaitedValue = await evaluateAsync(err.node, scope);
				// 继续异步执行剩余代码
				return await evaluateAsync(node, scope);
			})();
		}
		throw err; // 其他错误正常抛出
	}
}

function extractAsyncArrowFunctions(
  ast: any, 
  code: string,  // 原始代码字符串
  appendApi: Record<string, any> = {}
): Record<string, any> {
  const asyncFuncs: Record<string, any> = {};
  
  function traverse(node: any) {
    if (!node) return;

    // 定位 const func = async (...) => {} 形式的声明
    if (node.type === "VariableDeclaration" && node.kind === "const") {
      for (const decl of node.declarations) {
        // 检查是否是异步箭头函数
        if (decl.init?.type === "ArrowFunctionExpression" && decl.init.async) {
          const funcName = decl.id?.name;
          // 确保节点有位置信息（start/end）
          if (funcName && node.start !== undefined && node.end !== undefined) {
            // 1. 截取完整的函数声明代码（包括 const 定义）
            // 例如：const fetchData = async (url) => { ... }
            const fullFuncCode = code.slice(node.start, node.end);
            
            // 2. 创建独立临时作用域，注入API确保函数内依赖可用
            const tempScope = new Scope();
            Object.keys(defaultApi).forEach(k => tempScope.declare("const", k, defaultApi[k]));
            Object.keys(appendApi).forEach(k => tempScope.declare("const", k, appendApi[k]));
            
            try {
              // 3. 解析并执行原始函数声明代码，生成函数句柄
              const funcAst = acorn.parse(fullFuncCode, { ecmaVersion: 2022 });
              evaluateSync(funcAst, tempScope);
              
              // 4. 从临时作用域中获取函数句柄（原始代码生成的函数）
              const func = tempScope.find(funcName)?.$get();
              if (func) {
                asyncFuncs[funcName] = func;
              }
            } catch (e) {
              console.warn(`生成函数句柄失败 ${funcName}:`, e);
            }
          }
        }
      }
    }

    // 递归遍历子节点
    for (const key in node) {
      if (node[key] && typeof node[key] === "object") {
        Array.isArray(node[key]) 
          ? node[key].forEach((child: any) => traverse(child))
          : traverse(node[key]);
      }
    }
  }

  traverse(ast);
  return asyncFuncs;
}



/** ---------- 解释器入口 ---------- */
export function run(
	code: string,
	appendApi: Record<string, any> = {},
	options: { ecmaVersion?: number } = {}
): Promise<any> {
	const scope = new Scope(null, false, true); // 顶层作用域标记
	Object.keys(defaultApi).forEach((k) => {
		scope.declare("const", k, (defaultApi as any)[k]);
	});
	Object.keys(appendApi).forEach((k) => {
		scope.declare("const", k, appendApi[k]);
	});
	
	// 解析AST
	const ast = acorn.parse(code, {
		ecmaVersion: options.ecmaVersion || 2022,
		sourceType: "module"
	}) as any;
	
	// 传入原始代码，提取函数句柄
	const extractedFuncs = extractAsyncArrowFunctions(ast, code, appendApi);
	
	// 注入extractedFuncs
	Object.keys(extractedFuncs).forEach((k) => {
		scope.declare("const", k, extractedFuncs[k]);
	});
	
	const newAst = acorn.parse(code, {
		ecmaVersion: options.ecmaVersion || 2022,
		sourceType: "module"
	}) as any;

	// 执行结果可能是同步值或Promise（因顶层await）
	const result = evaluate(newAst, scope);
	// 确保返回Promise（兼容顶层await的异步结果）
	return result instanceof Promise ? result : Promise.resolve(result);
}
